<template>
    <div class="flex-cc fdc jcb">
        <el-table id="workTable" :data="data.tableData" @sort-change="sort"
            :cell-class-name="({ columnIndex: i, row }) => { if (i == 1) return row.class }"
            style="width: 100%;height: 85%;">
            <el-table-column label="名称" prop="name" sortable width="80" />
            <el-table-column label="值" prop="value" class-name="noWrap" />
            <el-table-column label="类型" prop="type" width="70" />
        </el-table>
        <div class="flex-cc" style="width: 100%;">
            <el-input v-model="data.value" @keydown.enter=" up || change(); up = 1" @keyup.enter="up = 0"
                placeholder="请输入内容"></el-input>
            <el-button @click="change" type="primary" style="margin-left: 10px;">输入</el-button>
        </div>
    </div>
</template>

<script setup>
import { ElMessage } from 'element-plus';
import { evaluate } from 'mathjs';
import { keywordObj } from './allConfig.js';



const {
    data
} = defineProps([
    'data'
])
function sort({ column, prop, order }) {
    console.log(column, prop, order);
}




/**
 * 给一个数字，返回一个格式化后的字符串
 * @param {number} i 需要格式化的数字
 */
function setNum(i) {
    if (typeof i != 'number') return;
    let xiaos = i.toFixed(4)
    let kex = i.toExponential(4)
    // console.log(i, xiaos, kex);
    return i % 1 ? xiaos.length < 10 ? xiaos : kex : i.toString().length < 10 ? i : kex
}


/**
 * 给一个复数对象，返回一个格式化后的字符串
 * @param {object} res 需要格式化的复数对象
 */
function getComplex(res) {
    return res.im ?
        res.im > 0 ?
            `${res.re.toFixed(4)} + ${res.im.toFixed(4)}i` :
            `${res.re.toFixed(4)} - ${res.im.toFixed(4).substr(1)}i`
        : res.re
}
function change() {
    if (!data.value) return;
    let str = data.value.trim()
    // console.log(keywordObj);
    // 排除部分情况
    if (!/^[^=]*={1}[^=]*$/.test(str)) return ElMessage.error('语法错误：表达式错误, = 缺失');
    let key = str.split('=')[0], value = str.split('=')[1], type = typeof value;

    // key规则
    if (key.length < 65) {
        if (key.includes(' ')) return ElMessage.error('变量错误：变量名中间不能有空格');
        if (!/^[a-zA-Z][_\da-zA-Z]*$/.test(key)) return ElMessage.error('变量错误：请输入正确的变量名');
        if (Object.keys(keywordObj).some(i => i.toLowerCase() == key.toLowerCase()))
            return ElMessage.error('变量错误：关键词不能作为变量名');
    } else return ElMessage.error('变量错误：变量名不能超过64个字符');

    // value规则
    if (/^[\[].*[\]]$/.test(value) && /[\'\"\`]/.test(value)) return ElMessage.error('语法错误：数组中只能出现数字');




    if (!/^[\'\"\`].*[\'\"\`]$/.test(value)) {


        // if (
        // /[\d]+[a-zA-Z]+/.test(value) &&
        // !/[\d]+e\+[\d]+/.test(value))
        // return ElMessage.error('变量错误：变量引用错误，请输入正确的变量名');




        // 处理有变量的情况
        if (/[a-zA-Z][\w]*/.test(value)) {
            let arr = value.match(/[a-zA-Z][_\da-zA-Z]*/g)
                .filter(i => !new Set(Object.keys(keywordObj).map(i => i.toLowerCase())).has(i.toLowerCase()))
            console.log(arr, value);
            for (const i of arr) {
                let pos = value.indexOf(i)
                if (value[pos - 1] == '.' || value[pos + 1] == '.')
                    return ElMessage.error('变量错误：变量前后不能跟 "."');


                let res = data.tableData.find(j => j.name == i)
                if (res) {
                    console.log(i, value, res, res.value, typeof res.value);
                    if (res.type.includes('F64_') &&
                        new RegExp(`(?<!\\w)${i}\\[[\\+\\-*/.()^\\d]+\\](?!\\w)`, 'gi').test(value)) {
                        console.log(value);
                    }
                    typeof res.value == 'string' && /^[\[].*[\]]$/.test(res.value) &&
                        (res.value = res.value.slice(1, -1));
                    let val = /\d/.test(value[pos - 1]) ? `*(${res.value})` : res.value
                    let reg = new RegExp(`(?<!a-zA-Z_)${i}(?!\\w)`)
                    value = value.replace(reg, val)
                    console.log(pos, i, value, /\d/.test(value[pos - 1]), val, reg, value);
                }
                // else if (value.match(/\((.*)\)/)?.[1][0] == '-') return ElMessage.error('参数错误：参数不能为负值');
                else return ElMessage.error('变量错误：变量 ' + i + ' 未找到');
            }
        }






        // 处理关键词的情况
        wai: for (const key of Object.keys(keywordObj)) {
            // console.log(key, value);
            if (value.toLowerCase().includes(key.toLowerCase())) {
                let res = [...new Set(value.match(keywordObj[key].reg))]
                console.log(key, value, res);
                if (res) {
                    for (const i of res) {
                        if (keywordObj[key].value) {
                            console.log(i, key, value, /[\d]i/.test(value));
                            if (key == 'i' && /[\d]i/.test(value)) continue wai;
                            value = value.replaceAll(i, keywordObj[key].value)
                        }
                        if (keywordObj[key].fn) {
                            let can = i.match(/\((.*)\)/)?.[1]
                            // console.log(i, can, key, i.match(/\((.*)\)/));
                            if (key == 'sqrt' && can < 0) continue;
                            try {
                                can = evaluate(can)
                            }
                            catch {
                                return ElMessage.error('语法错误：参数不合法');
                            }
                            // console.log(can, i, key, value, keywordObj[key].fn(can));
                            value = value.replaceAll(i, keywordObj[key].fn(can))
                        }
                        // console.log(value, key);
                    }
                }
            }
        }








        // 处理数字运算
        let arr, buhefa;
        if (/^[\[].*[\]]$/.test(value)) {
            arr = value.slice(1, -1).split(',')
        } else {
            arr = [value]
            type = 'F64'
        }
        // console.log(type, arr, value);
        if (arr) {
            // if (!arr.every(i => (i.includes('Infinity') || /^[\+\-*/.()^\de]+$/.test(i)) &&
            //     /^(?![*/])(?:[^*/]|(?<![*/+-])[*/+-])*(\d|Infinity)$/.test(i)))
            //     return ElMessage.error('语法错误：该运算表达式不合法');
            // arr = arr.map(i => evaluate(i) ?? '')
            arr = arr.map(i => {
                let res;
                console.log(i);
                try {
                    res = evaluate(i) ?? ''
                }
                catch {
                    buhefa = 1
                }
                console.log(res);
                if (res && res.type == 'Complex') {
                    res = getComplex(res)
                };
                return res
            })
            if (buhefa) return ElMessage.error('语法错误：该运算表达式不合法');
        }
        let special = {
            Infinity: 'Inf',
            '-Infinity': '-Inf',
            NaN: 'NaN'
        }
        arr = arr.map(i => special[i] ? `"${special[i]}"` : i)
        value = arr.length == 1 && type == 'F64' ? arr[0] ?? '[]' : `[${arr.join(',')}]`
        console.log(type, arr, value);
    }
    try {
        if (/^[\'\`].*[\'\`]$/.test(value) || /i/.test(value))
            value = `"${value}"`;
        value = JSON.parse(value)
        typeof value == 'object' && (value = value.map(i => setNum(i)))
        typeof value == 'number' && (value = setNum(value), type = 'F64')
    }
    catch {
        return ElMessage.error('语法错误：请检查表达式格式');
    }
    console.log(value);
    if (typeof value == 'object') {
        type = 'F64_' + value.length
        value.length ? value.length == 1 || (value = `[${value}]`) : value = '[ ]';
    }
    // console.log(key, value, type, typeof value, +value, value.length, value == "''" || value == "" || value == "``");
    if (typeof value == 'string') {
        if (value == "''" || value == "" || value == "``") return ElMessage.error('值不能为空');
        type != 'string' || /^[\'\`\[].*[\'\`\]]$/.test(value) || (value = `"${value}"`)
    }





    // // console.log(key, numJstr || value, typeof value, type);
    let typeObj = {
        // number: 'F64',
        string: 'STR',
    }
    let result = {
        name: key,
        value: value,
        // value: numJstr || value,
        type: Object.keys(typeObj).includes(type) ? typeObj[type] : type,
        class: type == 'F64_0' ? 'array' : null
    }
    // console.log(result);
    let index = data.tableData.findIndex(i => i.name == key)
    index + 1 ? data.tableData[index] = result : data.tableData.push(result)
    data.value = null
}
// function downChange() {
//     if (is_up) return;
//     change()
//     is_up = true;
// }
// function up() {
//     is_up = false;
// }
</script>

<style>
#workTable {
    .el-table__cell {
        user-select: all;
    }

    .array {
        font-style: italic;
        color: #22a6f2;
    }

    .noWrap div {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
}
</style>